home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 25 / AMIGAplus Sonderheft 25 (2000)(Falke)(DE)(Track 1 of 4)[!].iso / Updates / PowerPC / pdflib / pdflib / p_hyper.c < prev    next >
C/C++ Source or Header  |  2000-05-16  |  10KB  |  363 lines

  1. /*---------------------------------------------------------------------------*
  2.  |        PDFlib - A library for dynamically generating PDF files            |
  3.  +---------------------------------------------------------------------------+
  4.  |        Copyright (c) 1997-1999 Thomas Merz. All rights reserved.          |
  5.  +---------------------------------------------------------------------------+
  6.  |    This software is not in the public domain.  It is subject to the       |
  7.  |    "Aladdin Free Public License".  See the file license.txt for details.  |
  8.  |    This license grants you the right to use and redistribute PDFlib       |
  9.  |    under certain conditions. Among other things, the license requires     |
  10.  |    that the copyright notice and this notice be preserved on all copies.  |
  11.  |    This requirement extends to ports to other programming languages.      |
  12.  |                                                                           |
  13.  |    In short, you are allowed to develop and use PDFlib-based software     |
  14.  |    as long as you don't sell it. Commercial use of PDFlib requires a      |
  15.  |    commercial license which can be obtained from the author of PDFlib.    |
  16.  |    Contact information can be found in the accompanying PDFlib manual.    |
  17.  |    PDFlib is distributed with no warranty of any kind. Commercial users,  |
  18.  |    however, will receive warranty and support statements in writing.      |
  19.  *---------------------------------------------------------------------------*/
  20.  
  21. /* p_hyper.c
  22.  *
  23.  * PDFlib routines for hypertext stuff: bookmarks, document info, transitions
  24.  *
  25.  */
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30.  
  31. #include "p_intern.h"
  32.  
  33. /* We can't work with pointers in the outline objects because
  34.  * the complete outline block may be reallocated. Therefore we use
  35.  * this simple mechanism for achieving indirection.
  36.  */
  37. #define COUNT(index)    (p->outlines[index].count)
  38. #define OPEN(index)    (p->outlines[index].open)
  39. #define LAST(index)    (p->outlines[index].last)
  40. #define PARENT(index)    (p->outlines[index].parent)
  41. #define FIRST(index)    (p->outlines[index].first)
  42. #define SELF(index)    (p->outlines[index].self)
  43. #define PREV(index)    (p->outlines[index].prev)
  44. #define NEXT(index)    (p->outlines[index].next)
  45.  
  46. void
  47. pdf_init_outlines(PDF *p)
  48. {
  49.     p->outline_count    = 0;
  50. }
  51.  
  52. /* Free outline entries */
  53. void
  54. pdf_cleanup_outlines(PDF *p)
  55. {
  56.     int i;
  57.  
  58.     if (p->outline_count == 0)
  59.     return;
  60.  
  61.     /* outlines[0] is the outline root object */
  62.     for (i = 0; i <= p->outline_count; i++)
  63.     if (p->outlines[i].text)
  64.         p->free(p, p->outlines[i].text);
  65.  
  66.     p->free(p, (void*) p->outlines);
  67. }
  68.  
  69. static void
  70. pdf_write_outline_dict(PDF *p, int entry)
  71. {
  72.     pdf_begin_obj(p, SELF(entry));    /* outline object */
  73.     pdf_begin_dict(p);
  74.  
  75.     (void) fprintf(p->fp, "/Parent %ld 0 R\n", SELF(PARENT(entry)));
  76.  
  77.     /* outline destination */
  78.     (void) fprintf(p->fp, "/Dest [%ld 0 R /XYZ 0 0 0]\n", 
  79.         p->pages[p->outlines[entry].dest.page]);
  80.  
  81.     (void) fputs("/Title ", p->fp);    /* outline text */
  82.     pdf_quote_string(p, p->outlines[entry].text);
  83.     (void) fputs("\n", p->fp);
  84.  
  85.     if (PREV(entry))
  86.     (void) fprintf(p->fp, "/Prev %ld 0 R\n", PREV(entry));
  87.     if (NEXT(entry))
  88.     (void) fprintf(p->fp, "/Next %ld 0 R\n", NEXT(entry));
  89.  
  90.     if (FIRST(entry)) {
  91.     (void) fprintf(p->fp, "/First %ld 0 R\n", SELF(FIRST(entry)));
  92.     (void) fprintf(p->fp, "/Last %ld 0 R\n", SELF(LAST(entry)));
  93.     }
  94.     if (COUNT(entry)) {
  95.     if (OPEN(entry))
  96.         (void) fprintf(p->fp, "/Count %d\n", COUNT(entry));    /* open */
  97.     else
  98.         (void) fprintf(p->fp, "/Count %d\n", -COUNT(entry));/* closed */
  99.     }
  100.  
  101.     pdf_end_dict(p);
  102.     pdf_end_obj(p);            /* outline object */
  103. }
  104.  
  105. void
  106. pdf_write_outlines(PDF *p)
  107. {
  108.     int i;
  109.  
  110.     if (p->outline_count == 0)        /* no outlines: return */
  111.     return;
  112.  
  113.     pdf_begin_obj(p, p->outlines[0].self);    /* root outline object */
  114.     pdf_begin_dict(p);
  115.  
  116.     if (p->outlines[0].count != 0)
  117.     (void) fprintf(p->fp, "/Count %d\n", COUNT(0));
  118.     (void) fprintf(p->fp, "/First %ld 0 R\n", SELF(FIRST(0)));
  119.     (void) fprintf(p->fp, "/Last %ld 0 R\n", SELF(LAST(0)));
  120.  
  121.     pdf_end_dict(p);
  122.     pdf_end_obj(p);                /* root outline object */
  123.  
  124.     for (i = 1; i <= p->outline_count; i++)
  125.     pdf_write_outline_dict(p, i);
  126. }
  127.  
  128. PDFLIB_API int PDFLIB_CALL
  129. PDF_add_bookmark(PDF *p, const char *text, int parent, int open)
  130. {
  131.     pdf_outline *self;            /* newly created outline */
  132.  
  133.     if (text == NULL)
  134.     pdf_error(p, PDF_ValueError, "Null bookmark text");
  135.  
  136.     if (parent < 0 || parent > p->outline_count)
  137.     pdf_error(p, PDF_ValueError,
  138.         "Bad parent id %d for subordinate bookmark!", parent);
  139.  
  140.     /* create the root outline object */
  141.     if (p->outline_count == 0) {
  142.     p->outlines = (pdf_outline *) p->calloc(p, 
  143.         sizeof(pdf_outline) * OUTLINE_CHUNKSIZE, "PDF_add_bookmark");
  144.     p->outline_capacity = OUTLINE_CHUNKSIZE;
  145.  
  146.     /* populate the root outline object */
  147.     p->outlines[0].self    = pdf_alloc_id(p);
  148.     p->outlines[0].count    = 0;
  149.     p->outlines[0].parent    = 0;
  150.     p->outlines[0].open    = 1;
  151.     }
  152.  
  153.     /* It's crucial to increase p->outline_count only after 
  154.      * successfully having realloc()ed. Otherwise the error handler
  155.      * may try to free to much if the realloc goes wrong.
  156.      */
  157.     if (p->outline_count+1 >= p->outline_capacity) { /* used up all space */
  158.     p->outlines = (pdf_outline *) p->realloc(p, p->outlines,
  159.             sizeof(pdf_outline) * 2 * p->outline_capacity,
  160.             "PDF_add_bookmark");
  161.     p->outline_capacity *= 2;
  162.     }
  163.  
  164.     p->outline_count++;
  165.  
  166.     self = &p->outlines[p->outline_count];
  167.  
  168.     /* If the error handler pops in in pdf_strdup below, we don't
  169.      * want to have the cleanup function try to free self->text.
  170.      */
  171.     self->text        = NULL;
  172.  
  173.     self->text        = pdf_strdup(p, text);
  174.     self->dest.page    = p->current_page;
  175.     self->self        = pdf_alloc_id(p);
  176.     self->first        = 0;
  177.     self->last        = 0;
  178.     self->prev        = 0;
  179.     self->next        = 0;
  180.     self->count        = 0;
  181.     self->open        = open;
  182.     self->parent    = parent;
  183.  
  184.     /* insert new outline at the end of the chain or start a new chain */
  185.     if (FIRST(parent) == 0) {
  186.     FIRST(parent) = p->outline_count;
  187.     } else {
  188.     self->prev = SELF(LAST(parent));
  189.     NEXT(LAST(parent))= self->self;
  190.     }
  191.  
  192.     /* insert new outline as last child of parent in all cases */
  193.     LAST(parent) = p->outline_count;
  194.  
  195.     /* increase the number of open sub-entries for all relevant ancestors */
  196.     do {
  197.     COUNT(parent)++;
  198.     } while (OPEN(parent) && (parent = PARENT(parent)) != 0);
  199.  
  200.     return (p->outline_count);        /* caller may use this as handle */
  201. }
  202.  
  203. void
  204. pdf_init_info(PDF *p)
  205. {
  206.     p->Keywords        = NULL;
  207.     p->Subject        = NULL;
  208.     p->Title        = NULL;
  209.     p->Creator        = NULL;
  210.     p->Author        = NULL;
  211.     p->userkey        = NULL;
  212.     p->userval        = NULL;
  213.  
  214.     p->info_id        = pdf_alloc_id(p);    /* Info object */
  215. }
  216.  
  217. /* Set Info dictionary entries */
  218. PDFLIB_API void PDFLIB_CALL
  219. PDF_set_info(PDF *p, const char *key, const char *val)
  220. {
  221.     char *key_buf, *val_buf;
  222.  
  223.     if (key == NULL || val == NULL) {
  224.     pdf_error(p, PDF_NonfatalError, "Null key or value in PDF_set_info");
  225.     return;
  226.     }
  227.  
  228.     /* this is needed in all cases */
  229.     val_buf = pdf_strdup(p, val);
  230.  
  231.     if (!strcmp(key, "Keywords")) {
  232.     p->Keywords = val_buf;
  233.     } else if (!strcmp(key, "Subject")) {
  234.     p->Subject = val_buf;
  235.     } else if (!strcmp(key, "Title")) {
  236.     p->Title = val_buf;
  237.     } else if (!strcmp(key, "Creator")) {
  238.     p->Creator = val_buf;
  239.     } else if (!strcmp(key, "Author")) {
  240.     p->Author = val_buf;
  241.     } else {
  242.     /* user-defined keyword */
  243.     p->userval = val_buf;
  244.  
  245.     key_buf = pdf_strdup(p, key);
  246.     p->userkey = key_buf;
  247.     }
  248. }
  249.  
  250. void
  251. pdf_write_info(PDF *p)
  252. {
  253.     time_t    timer;
  254.     struct tm    ltime;
  255.  
  256.     pdf_begin_obj(p, p->info_id);    /* Info object */
  257.  
  258.     pdf_begin_dict(p);
  259.  
  260.     if (p->Keywords) {
  261.     (void) fprintf(p->fp, "/Keywords ");
  262.     pdf_quote_string(p, p->Keywords);
  263.     (void) fprintf(p->fp, "\n");
  264.     }
  265.     if (p->Subject) {
  266.     (void) fprintf(p->fp, "/Subject ");
  267.     pdf_quote_string(p, p->Subject);
  268.     (void) fprintf(p->fp, "\n");
  269.     }
  270.     if (p->Title) {
  271.     (void) fprintf(p->fp, "/Title ");
  272.     pdf_quote_string(p, p->Title);
  273.     (void) fprintf(p->fp, "\n");
  274.     }
  275.     if (p->Creator) {
  276.     (void) fprintf(p->fp, "/Creator ");
  277.     pdf_quote_string(p, p->Creator);
  278.     (void) fprintf(p-